﻿
using ST.Core.Util;
using ST.Data;
using ST.ModelVM.ProtocolDefine;
using ST.ModelVM.ProtocolSimLog;

namespace ST.Receiver.Tasks
{
    public class SimWorker : BackgroundService
    {
        const int DELAY_SHORT_MS = 50;
        public Int64 Id { get; set; }   
        public Data.ProtocolDefine ProtocolDefine { get; set; }
        public Data.ProtocolSim ProtocolSim { get; set; }
        public List<Data.ProtocolSimHost> ProtocolSimHostList { get; set; }

        public List<SimHostWorker> SimHostWorkerList { get; set; } = new List<SimHostWorker>();
        CancellationTokenSource BreakCancellationTokenSource { get; set; } = new CancellationTokenSource();
        CancellationToken BreakToken
        {
            get
            {
                return BreakCancellationTokenSource.Token;
            }
        }
        CancellationToken EndToken { get; set; }
      

        ILogger<SimWorker> _logger;

        bool IsFirst = true;
        public  BaseConnection BaseConnection { get; set; }
        Data.ProtocolSim CurrProtocolSim;

        public SimWorker(ILogger<SimWorker> logger)
        {
            _logger = logger;
        }
        protected async override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            this.EndToken= stoppingToken;
            _logger.LogInformation($"TransWorker {ProtocolSim.Name}  开始。。。。");             
            TransMain.Instance.AddSimLog(ProtocolSim.Id, 0, "采集器", new byte[] { 0x0 }, $"{ProtocolSim.Name}启动");
            if (this.ProtocolSim.Mode == "TCP")
            {
                BaseConnection = new TcpConnection();
                BaseConnection.SimWorker = this;
                
            }
            else if (this.ProtocolSim.Mode == "UDP")
            {
                BaseConnection = new UdpConnection();
                BaseConnection.SimWorker = this;

            }
            else if (this.ProtocolSim.Mode == "串口")
            {
                BaseConnection = new PortConnection();
                BaseConnection.SimWorker = this;

            }

            foreach (var mm in ProtocolSimHostList)
            {
                var mhost=new SimHostWorker(this,mm);
                SimHostWorkerList.Add(mhost);   
            }
            while (!EndToken.IsCancellationRequested)
            {
                try {

                    var c = CheckBreak();
                    if (c == 2)
                    {
                        break;//结束
                    }
                    if (c == 1)//终端
                    {
                        await MyDeay(DELAY_SHORT_MS);
                        continue;
                    }
                    if (!BaseConnection.IsOpen())
                    {
                        await MyDeay(DELAY_SHORT_MS);
                        BaseConnection.Open(ProtocolSim);
                        continue;
                    }

                    foreach (var mm in SimHostWorkerList)
                    {
                        if (IsFirst)
                        {
                            var r = await mm.DoFirstAsync();
                        }
                        else
                        {
                            var r = await mm.DoLoopAsync();
                        }
                    }
                    await MyDeay(DELAY_SHORT_MS);
                    IsFirst = false;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message ?? "");
                    _logger.LogError(ex.StackTrace ?? "");
                }
                
                
                BaseConnection.Close();
            }
            _logger.LogInformation($"TransWorker:{ProtocolSim.Name} 任务结束");
            TransMain.Instance.AddSimLog(ProtocolSim.Id, 0, "采集器", new byte[] { 0x0 }, $"{ProtocolSim.Name}停止");
        }


        public async Task<int> CmdAsync(ProtocolCmdVM qm)
        {
            try
            {
                BreakCancellationTokenSource.Cancel();
                await Task.Delay(DELAY_SHORT_MS);
                var mhost = SimHostWorkerList.Where(a => a.ProtocolSimHost.Id == qm.ProtocolSimHostId).FirstOrDefault();
                var  r=await mhost.CmdAsync(qm);

                IsFirst = true;

                return r ;
                
            }
            catch
            { }
            finally
            {
                BreakCancellationTokenSource = new CancellationTokenSource();
            }
            return 5;
        }

        #region 公共函数
        /// <summary>
        /// 等待
        /// </summary>
        /// <param name="millisecondsDelay"></param>
        /// <returns>0 正常  BreakToken  1  EndToken 2</returns>
        public async Task<int> MyDeay(int millisecondsDelay)
        {
            try
            {
                // 启动一个带有 CancellationToken 的 Task.Delay 任务
                await Task.Delay(millisecondsDelay, BreakToken);
                
            }
            catch (OperationCanceledException)
            {
                // 捕获到 OperationCanceledException 异常，说明任务是被取消的
                Console.WriteLine("任务被取消。");
                return 1;
            }
            return EndToken.IsCancellationRequested ? 2 : 0;

        }

        /// <summary>
        /// 等待
        /// </summary>
        /// <param name="millisecondsDelay"></param>
        /// <returns>0 正常  BreakToken  1  EndToken 2</returns>
        public async Task<int> MyDeayForEnd(int millisecondsDelay)
        {
            try
            {
                // 启动一个带有 CancellationToken 的 Task.Delay 任务
                await Task.Delay(millisecondsDelay, EndToken);

            }
            catch (OperationCanceledException)
            {
                // 捕获到 OperationCanceledException 异常，说明任务是被取消的
                Console.WriteLine("任务被取消。");
                return 1;
            }
            return EndToken.IsCancellationRequested ? 2 : 0;

        }

        /// <summary>
        /// 等待
        /// </summary>
        /// <param name="millisecondsDelay"></param>
        /// <returns>0 正常  BreakToken  1  EndToken 2  超时3</returns>
        public async Task<int> SendAndRev(SimHostWorker shw, ReqAndRevVM mm)
        {
            
            return await BaseConnection.SendAndRev(shw.ProtocolSimHost , mm);

        }


        /// <summary>
        /// 等待
        /// </summary>
        /// <param name="millisecondsDelay"></param>
        /// <returns>0 正常  BreakToken  1  EndToken 2  超时3</returns>
        public async Task<int> CmdAndRev(SimHostWorker shw, ReqAndRevVM mm)
        {

            return await BaseConnection.CmdAndRev(shw.ProtocolSimHost, mm);

        }



        /// <summary>
        /// 检测终端状态
        /// </summary>
        /// <param name="millisecondsDelay"></param>
        /// <returns>0 正常  BreakToken  1  EndToken 2</returns>
        public int CheckBreak()
        {
            if (BreakToken.IsCancellationRequested)
            {
                return 1;
            }
            if (EndToken.IsCancellationRequested)
            {
                return 2;
            }
            return 0;
        }

       public static byte GetByteFromModbusData(byte[] data, int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            return data[index];
        }
        public static ushort GetUInt16FromModbusData(byte[] data, int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index + 1 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            return (ushort)((data[index] << 8) | data[index + 1]);
        }

        public static int GetInt32FromModbusData(byte[] data, int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index + 3 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            return (data[index] << 24) | (data[index + 1] << 16) | 
                (data[index + 2] << 8) | data[index + 3];
        }

        public static float GetFloatFromModbusData(byte[] data, int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index + 3 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            
            // 将四个字节按照大端序组合成一个整数
            int intValue = (data[index] << 24) | (data[index + 1] << 16) | 
                        (data[index + 2] << 8) | data[index + 3];
            
            // 将整数转换为浮点数
            byte[] floatBytes = BitConverter.GetBytes(intValue);
            return BitConverter.ToSingle(floatBytes, 0);
        }
        public static byte GetBitFromModbusData(byte[] data, int index)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (index < 0 || index / 8 >= data.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            
            int byteIndex = index / 8;  // 计算字节索引
            int bitIndex = index % 8;    // 计算位索引
            return (data[byteIndex] & (1 << bitIndex) )!= 0 ? (byte)1 : (byte)0  ;
        }
        #endregion
        
    }
}
